package me.hys.service.chat.impl;

import java.util.ArrayList;
import java.util.List;

import me.hys.chat.JerseyUtils;
import me.hys.chat.comm.ChatConstants;
import me.hys.chat.comm.ChatException;
import me.hys.chat.comm.ChatExceptionEnum;
import me.hys.chat.comm.HTTPMethod;
import me.hys.chat.comm.Roles;
import me.hys.chat.vo.ClientSecretCredential;
import me.hys.chat.vo.Credential;
import me.hys.chat.vo.EndPoints;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.glassfish.jersey.client.JerseyWebTarget;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
 * Author: @author HYS . <br>
 * Date: 2015-10-6 上午1:21:21 . <br>
 * Function:
 */
public class BaseChatManagerImpl {
	protected final JsonNodeFactory factory = new JsonNodeFactory(false);
	protected final String APPKEY = ChatConstants.APPKEY;
	protected Credential credential = new ClientSecretCredential(
			ChatConstants.APP_CLIENT_ID, ChatConstants.APP_CLIENT_SECRET,
			Roles.USER_ROLE_APPADMIN);

	/**
	 * @Title : createNewIMUserSingle
	 * @Description : 创建单个用户
	 */
	protected ObjectNode createNewIMUserSingle(ObjectNode dataNode)
			throws ChatException {
		ObjectNode objectNode = factory.objectNode();
		// check appKey format
		if (!JerseyUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", APPKEY)) {
			throw new ChatException(ChatExceptionEnum.APP_KEY_ERROR.getCode(),
					ChatExceptionEnum.APP_KEY_ERROR.getMsg());
		}
		objectNode.removeAll();
		if (null != dataNode && !dataNode.has("username")) {
			throw new ChatException(
					ChatExceptionEnum.USERNAME_NOT_NULL.getCode(),
					ChatExceptionEnum.USERNAME_NOT_NULL.getMsg());
		}
		if (null != dataNode && !dataNode.has("password")) {
			throw new ChatException(
					ChatExceptionEnum.PASSWORD_NOT_NULL.getCode(),
					ChatExceptionEnum.PASSWORD_NOT_NULL.getMsg());
		}
		JerseyWebTarget webTarget = EndPoints.USERS_TARGET.resolveTemplate(
				"org_name", APPKEY.split("#")[0]).resolveTemplate("app_name",
				APPKEY.split("#")[1]);
		objectNode = JerseyUtils.sendRequest(webTarget, dataNode, credential,
				HTTPMethod.METHOD_POST, null);
		return objectNode;
	}

	/**
	 * @Title : deleteIMUserByUserName
	 * @Description : 删除单个用户
	 */
	protected ObjectNode deleteIMUserByUserName(String userName)
			throws ChatException {
		ObjectNode objectNode = factory.objectNode();
		// check appKey format
		if (!JerseyUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", APPKEY)) {
			throw new ChatException(ChatExceptionEnum.APP_KEY_ERROR.getCode(),
					ChatExceptionEnum.APP_KEY_ERROR.getMsg());
		}
		try {
			JerseyWebTarget webTarget = EndPoints.USERS_TARGET
					.resolveTemplate("org_name", APPKEY.split("#")[0])
					.resolveTemplate("app_name", APPKEY.split("#")[1])
					.path(userName);
			objectNode = JerseyUtils.sendRequest(webTarget, null, credential,
					HTTPMethod.METHOD_DELETE, null);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return objectNode;
	}

	/**
	 * 获取聊天消息
	 * 
	 * @param queryStrNode
	 * 
	 */
	protected ObjectNode getChatMessages(ObjectNode queryStrNode) {
		ObjectNode objectNode = factory.objectNode();
		// check appKey format
		if (!JerseyUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", APPKEY)) {
			// LOGGER.error("Bad format of Appkey: " + APPKEY);
			objectNode.put("message", "Bad format of Appkey");
			return objectNode;
		}
		try {
			JerseyWebTarget webTarget = EndPoints.CHATMESSAGES_TARGET
					.resolveTemplate("org_name", APPKEY.split("#")[0])
					.resolveTemplate("app_name", APPKEY.split("#")[1]);
			if (null != queryStrNode && null != queryStrNode.get("ql")
					&& !StringUtils.isEmpty(queryStrNode.get("ql").asText())) {
				webTarget = webTarget.queryParam("ql", queryStrNode.get("ql")
						.asText());
			}
			if (null != queryStrNode && null != queryStrNode.get("limit")
					&& !StringUtils.isEmpty(queryStrNode.get("limit").asText())) {
				webTarget = webTarget.queryParam("limit",
						queryStrNode.get("limit").asText());
			}
			if (null != queryStrNode
					&& null != queryStrNode.get("cursor")
					&& !StringUtils
							.isEmpty(queryStrNode.get("cursor").asText())) {
				webTarget = webTarget.queryParam("cursor",
						queryStrNode.get("cursor").asText());
			}
			objectNode = JerseyUtils.sendRequest(webTarget, null, credential,
					HTTPMethod.METHOD_GET, null);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return objectNode;
	}

	/**
	 * @Title : imUserLogin
	 * @Description : 用户登录
	 */
	protected ObjectNode imUserLogin(String username, String password)
			throws ChatException {
		ObjectNode objectNode = factory.objectNode();
		if (!JerseyUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", APPKEY)) {
			throw new ChatException(ChatExceptionEnum.APP_KEY_ERROR.getCode(),
					ChatExceptionEnum.APP_KEY_ERROR.getMsg());
		}
		if (StringUtils.isEmpty(username)) {
			throw new ChatException(
					ChatExceptionEnum.USERNAME_NOT_NULL.getCode(),
					ChatExceptionEnum.USERNAME_NOT_NULL.getMsg());
		}
		if (StringUtils.isEmpty(password)) {
			throw new ChatException(
					ChatExceptionEnum.PASSWORD_NOT_NULL.getCode(),
					ChatExceptionEnum.PASSWORD_NOT_NULL.getMsg());
		}
		try {
			ObjectNode dataNode = factory.objectNode();
			dataNode.put("grant_type", "password");
			dataNode.put("username", username);
			dataNode.put("password", password);
			List<NameValuePair> headers = new ArrayList<NameValuePair>();
			headers.add(new BasicNameValuePair("Content-Type",
					"application/json"));
			objectNode = JerseyUtils.sendRequest(EndPoints.TOKEN_APP_TARGET
					.resolveTemplate("org_name", APPKEY.split("#")[0])
					.resolveTemplate("app_name", APPKEY.split("#")[1]),
					dataNode, null, HTTPMethod.METHOD_POST, headers);
		} catch (Exception e) {
			throw new ChatException(ChatExceptionEnum.TOKEN_ERROR.getCode(),
					ChatExceptionEnum.TOKEN_ERROR.getMsg());
		}
		return objectNode;
	}

	/**
	 * @Title : isOnline
	 * @Description : 用户是否在线
	 */
	protected ObjectNode isOnline(String targetUserName) throws ChatException {
		ObjectNode objectNode = factory.objectNode();
		// check appKey format
		if (!JerseyUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", APPKEY)) {
			throw new ChatException(ChatExceptionEnum.APP_KEY_ERROR.getCode(),
					ChatExceptionEnum.APP_KEY_ERROR.getMsg());
		}
		if (StringUtils.isEmpty(targetUserName)) {
			throw new ChatException(
					ChatExceptionEnum.USERNAME_NOT_NULL.getCode(),
					ChatExceptionEnum.USERNAME_NOT_NULL.getMsg());
		}
		JerseyWebTarget webTarget = EndPoints.USERS_TARGET
				.resolveTemplate("org_name", APPKEY.split("#")[0])
				.resolveTemplate("app_name", APPKEY.split("#")[1])
				.path(targetUserName).path("status");

		objectNode = JerseyUtils.sendRequest(webTarget, null, credential,
				HTTPMethod.METHOD_GET, null);
		return objectNode;
	}

	/**
	 * @Title : modifyIMUserNicknameWithAdminToken
	 * @Description : 修改昵称
	 */
	protected ObjectNode modifyIMUserNicknameWithAdminToken(String userName,
			ObjectNode dataObjectNode) throws ChatException {
		ObjectNode objectNode = factory.objectNode();
		if (!JerseyUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", APPKEY)) {
			throw new ChatException(ChatExceptionEnum.APP_KEY_ERROR.getCode(),
					ChatExceptionEnum.APP_KEY_ERROR.getMsg());
		}
		if (StringUtils.isEmpty(userName)) {
			throw new ChatException(
					ChatExceptionEnum.USERNAME_NOT_NULL.getCode(),
					ChatExceptionEnum.USERNAME_NOT_NULL.getMsg());
		}
		if (null != dataObjectNode && !dataObjectNode.has("nickname")) {
			throw new ChatException(
					ChatExceptionEnum.NICKNAME_NOT_NULL.getCode(),
					ChatExceptionEnum.NICKNAME_NOT_NULL.getMsg());
		}
		JerseyWebTarget webTarget = EndPoints.USERS_TARGET
				.resolveTemplate("org_name", APPKEY.split("#")[0])
				.resolveTemplate("app_name", APPKEY.split("#")[1])
				.path(userName);
		objectNode = JerseyUtils.sendRequest(webTarget, dataObjectNode,
				credential, HTTPMethod.METHOD_PUT, null);
		return objectNode;
	}

	/**
	 * @Title : modifyIMUserPasswordWithAdminToken
	 * @Description : 重置密码
	 */
	protected ObjectNode modifyIMUserPasswordWithAdminToken(String userName,
			ObjectNode dataObjectNode) throws ChatException {
		ObjectNode objectNode = factory.objectNode();
		// check appKey format
		if (!JerseyUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", APPKEY)) {
			throw new ChatException(ChatExceptionEnum.APP_KEY_ERROR.getCode(),
					ChatExceptionEnum.APP_KEY_ERROR.getMsg());
		}
		if (StringUtils.isEmpty(userName)) {
			throw new ChatException(
					ChatExceptionEnum.USERNAME_NOT_NULL.getCode(),
					ChatExceptionEnum.USERNAME_NOT_NULL.getMsg());
		}
		if (null != dataObjectNode && !dataObjectNode.has("newpassword")) {
			throw new ChatException(
					ChatExceptionEnum.PASSWORD_NOT_NULL.getCode(),
					ChatExceptionEnum.PASSWORD_NOT_NULL.getMsg());
		}
		JerseyWebTarget webTarget = EndPoints.USERS_TARGET
				.resolveTemplate("org_name", APPKEY.split("#")[0])
				.resolveTemplate("app_name", APPKEY.split("#")[1])
				.path(userName).path("password");
		objectNode = JerseyUtils.sendRequest(webTarget, dataObjectNode,
				credential, HTTPMethod.METHOD_PUT, null);
		return objectNode;
	}

	/**
	 * 发送消息
	 * 
	 * @param targetType
	 *            消息投递者类型：users 用户, chatgroups 群组
	 * @param target
	 *            接收者ID 必须是数组,数组元素为用户ID或者群组ID
	 * @param msg
	 *            消息内容
	 * @param from
	 *            发送者
	 * @param ext
	 *            扩展字段
	 * 
	 * @return 请求响应
	 */
	protected ObjectNode sendMessages(ArrayNode target, ObjectNode msg,
			String from, ObjectNode ext) throws ChatException {
		ObjectNode objectNode = factory.objectNode();
		ObjectNode dataNode = factory.objectNode();
		// check appKey format
		if (!JerseyUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", APPKEY)) {
			throw new ChatException(ChatExceptionEnum.APP_KEY_ERROR.getCode(),
					ChatExceptionEnum.APP_KEY_ERROR.getMsg());
		}
		// 构造消息体
		dataNode.put("target_type", "users");
		dataNode.set("target", target);
		dataNode.set("msg", msg);
		dataNode.put("from", from);
		if (null != ext) {
			dataNode.set("ext", ext);
		}
		JerseyWebTarget webTarget = EndPoints.MESSAGES_TARGET.resolveTemplate(
				"org_name", APPKEY.split("#")[0]).resolveTemplate("app_name",
				APPKEY.split("#")[1]);

		objectNode = JerseyUtils.sendRequest(webTarget, dataNode, credential,
				HTTPMethod.METHOD_POST, null);
		return objectNode;
	}

}
